"""
Live2D 模型自动下载脚本
尝试从多个源下载 Hiyori 示例模型
"""

import os
import sys
import urllib.request
from pathlib import Path
import zipfile

# 模型下载源列表（按优先级）
MODEL_SOURCES = [
    {
        "name": "Gitee 镜像源 (国内)",
        "base_url": "https://gitee.com/mirrors_Live2D/CubismWebSamples/raw/master/Samples/Resources/Hiyori/",
        "files": [
            "hiyori_free_en.model3.json",
            "hiyori_free_en.moc3",
            "hiyori_free_en.physics3.json",
            "textures/texture_00.png"
        ],
        "type": "files"
    },
    {
        "name": "jsDelivr CDN (国内加速)",
        "base_url": "https://cdn.jsdelivr.net/gh/Live2D/CubismWebSamples@master/Samples/Resources/Hiyori/",
        "files": [
            "hiyori_free_en.model3.json",
            "hiyori_free_en.moc3",
            "hiyori_free_en.physics3.json",
            "textures/texture_00.png"
        ],
        "type": "files"
    },
    {
        "name": "GitHub Raw (备用1)",
        "base_url": "https://raw.githubusercontent.com/Live2D/CubismWebSamples/master/Samples/Resources/Hiyori/",
        "files": [
            "hiyori_free_en.model3.json",
            "hiyori_free_en.moc3",
            "hiyori_free_en.physics3.json",
            "textures/texture_00.png"
        ],
        "type": "files"
    },
    {
        "name": "Live2D 官方 CDN",
        "url": "https://cdn.live2d.com/cubism-web-samples/CubismSdkForWeb-4-r.7/Samples/Resources/Hiyori/Hiyori.2048.zip",
        "type": "zip"
    },
    {
        "name": "GitHub Raw (pixi备用)",
        "base_url": "https://raw.githubusercontent.com/guansss/pixi-live2d-display/master/test/assets/hiyori/",
        "files": [
            "hiyori_free_en.model3.json",
            "hiyori_free_en.moc3",
            "hiyori_free_en.physics3.json",
            "textures/texture_00.png"
        ],
        "type": "files"
    }
]

def download_file(url, dest_path, desc=""):
    """下载单个文件"""
    try:
        print(f"  下载: {desc or url}")
        
        # 创建目标目录
        dest_path.parent.mkdir(parents=True, exist_ok=True)
        
        # 下载文件
        urllib.request.urlretrieve(url, dest_path)
        
        print(f"  ✓ 成功: {dest_path.name}")
        return True
    except Exception as e:
        print(f"  ✗ 失败: {e}")
        return False


def download_zip_source(source, model_dir):
    """从 ZIP 源下载"""
    print(f"\n尝试从 {source['name']} 下载...")
    
    zip_path = model_dir / "temp_model.zip"
    
    try:
        if download_file(source['url'], zip_path, "模型压缩包"):
            try:
                print("  解压文件...")
                with zipfile.ZipFile(zip_path, 'r') as zip_ref:
                    zip_ref.extractall(model_dir)
                
                print(f"✓ 从 {source['name']} 下载成功！")
                return True
            except Exception as e:
                print(f"  ✗ 解压失败: {e}")
                return False
            finally:
                # 确保总是删除 zip 文件
                if zip_path.exists():
                    try:
                        zip_path.unlink()
                    except Exception as e:
                        print(f"  ⚠ 删除 zip 文件失败: {e}")
    except Exception as e:
        print(f"  ✗ 下载失败: {e}")
        # 清理可能存在的临时文件
        if zip_path.exists():
            try:
                zip_path.unlink()
            except:
                pass
    
    return False


def download_files_source(source, model_dir):
    """从文件列表源下载"""
    print(f"\n尝试从 {source['name']} 下载...")
    
    success_count = 0
    total_count = len(source['files'])
    
    for file_path in source['files']:
        url = source['base_url'] + file_path
        dest_path = model_dir / file_path
        
        if download_file(url, dest_path, file_path):
            success_count += 1
    
    if success_count == total_count:
        print(f"✓ 从 {source['name']} 下载成功！({success_count}/{total_count} 个文件)")
        return True
    elif success_count > 0:
        print(f"⚠ 部分成功: {success_count}/{total_count} 个文件")
    
    return False


def verify_model(model_dir):
    """验证模型文件"""
    required_files = [
        "hiyori_free_en.model3.json",
        "hiyori_free_en.moc3"
    ]
    
    print("\n验证模型文件...")
    all_exist = True
    
    for file_name in required_files:
        file_path = model_dir / file_name
        if file_path.exists():
            size = file_path.stat().st_size
            print(f"  ✓ {file_name} ({size:,} bytes)")
        else:
            print(f"  ✗ {file_name} (缺失)")
            all_exist = False
    
    return all_exist


def main():
    """主函数"""
    print("=" * 60)
    print("Live2D 模型自动下载工具")
    print("=" * 60)
    
    # 设置模型目录
    project_root = Path(__file__).parent
    model_dir = project_root / "models" / "hiyori"
    
    print(f"\n目标目录: {model_dir}")
    
    # 检查目录是否已有文件
    if model_dir.exists() and any(model_dir.iterdir()):
        print("\n⚠ 警告: 目标目录已存在文件")
        choice = input("是否覆盖？(y/n): ").strip().lower()
        if choice != 'y':
            print("取消下载")
            return
    
    # 创建目录
    model_dir.mkdir(parents=True, exist_ok=True)
    
    # 尝试各个下载源
    success = False
    for source in MODEL_SOURCES:
        try:
            if source['type'] == 'zip':
                success = download_zip_source(source, model_dir)
            elif source['type'] == 'files':
                success = download_files_source(source, model_dir)
            
            if success:
                break
        except Exception as e:
            print(f"✗ {source['name']} 下载失败: {e}")
            continue
    
    # 验证结果
    if success and verify_model(model_dir):
        print("\n" + "=" * 60)
        print("✓ Live2D 模型下载完成！")
        print("=" * 60)
        print(f"\n模型位置: {model_dir}")
        print("\n下一步:")
        print("1. 运行验证脚本: python verify_live2d_model.py")
        print("2. 启动完整系统: python main.py")
    else:
        print("\n" + "=" * 60)
        print("✗ 自动下载失败")
        print("=" * 60)
        print("\n请参考 LIVE2D_DOWNLOAD_GUIDE.md 手动下载模型")
        print("\n可选方案:")
        print("1. 使用浏览器手动下载")
        print("2. 先使用简化模式: python demo_without_live2d.py --auto")


if __name__ == "__main__":
    main()
